package com.kexio.common.entity;

import java.io.Serializable;
import java.time.LocalDateTime;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;

/**
 * 基础实体类
 * 
 * 包含所有实体的通用字段，提供统一的审计和多租户支持。
 * 所有业务实体都应继承此类以获得统一的基础功能。
 * 
 * 功能特性：
 * - 多租户支持：租户ID字段，可通过配置开关控制
 * - 审计字段：创建人、创建时间、更新人、更新时间
 * - 软删除：逻辑删除标记
 * - 自动填充：通过MyBatis拦截器自动填充审计字段
 * - 版本控制：乐观锁支持（可选）
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
public abstract class BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 租户ID
     * 
     * 多租户场景下的租户标识。
     * 通过配置 kexio.auth.tenant.enabled 控制是否启用。
     * 当启用多租户时，所有查询和操作都会自动添加租户过滤条件。
     */
    @TableField(value = "tenant_id", fill = FieldFill.INSERT)
    @JsonIgnore
    private String tenantId;

    /**
     * 创建人ID
     * 
     * 记录创建该记录的用户ID。
     * 通过MyBatis拦截器在插入时自动填充。
     */
    @TableField(value = "create_by", fill = FieldFill.INSERT)
    @JsonIgnore
    private String createBy;

    /**
     * 创建时间
     * 
     * 记录创建时间。
     * 通过MyBatis拦截器在插入时自动填充。
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    /**
     * 更新人ID
     * 
     * 记录最后更新该记录的用户ID。
     * 通过MyBatis拦截器在插入和更新时自动填充。
     */
    @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
    @JsonIgnore
    private String updateBy;

    /**
     * 更新时间
     * 
     * 记录最后更新时间。
     * 通过MyBatis拦截器在插入和更新时自动填充。
     */
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

    /**
     * 删除标记
     * 
     * 0表示未删除，1表示已删除。
     * 默认物理删除，子类可重写此字段并添加@TableLogic注解来启用逻辑删除。
     */
    @TableField(value = "deleted", fill = FieldFill.INSERT)
    @JsonIgnore
    protected Integer deleted;

    /**
     * 版本号（乐观锁）
     * 
     * 用于乐观锁控制，防止并发更新冲突。
     * 可选字段，不是所有实体都需要版本控制。
     */
//    @Version
//    @TableField(value = "version", fill = FieldFill.INSERT)
//    @JsonIgnore
//    private Long version;

    /**
     * 备注
     * 
     * 通用备注字段，业务实体可以用于存储额外信息。
     */
    @TableField(value = "remark")
    private String remark;

    // ==================== Getter和Setter方法 ====================

    public String getTenantId() {
        return tenantId;
    }

    public void setTenantId(String tenantId) {
        this.tenantId = tenantId;
    }

    public String getCreateBy() {
        return createBy;
    }

    public void setCreateBy(String createBy) {
        this.createBy = createBy;
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public String getUpdateBy() {
        return updateBy;
    }

    public void setUpdateBy(String updateBy) {
        this.updateBy = updateBy;
    }

    public LocalDateTime getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(LocalDateTime updateTime) {
        this.updateTime = updateTime;
    }

    public Integer getDeleted() {
        return deleted;
    }

    public void setDeleted(Integer deleted) {
        this.deleted = deleted;
    }

//    public Long getVersion() {
//        return version;
//    }
//
//    public void setVersion(Long version) {
//        this.version = version;
//    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    // ==================== 实用方法 ====================

    /**
     * 判断是否为新记录
     * 
     * 子类可以重写此方法来定义自己的判断逻辑。
     * 默认通过createTime是否为空来判断。
     * 
     * @return true-新记录，false-已存在记录
     */
    public boolean isNew() {
        return this.createTime == null;
    }

    /**
     * 判断记录是否已删除
     * 
     * @return true-已删除，false-未删除
     */
    public boolean checkDeleted() {
        return this.deleted != null && this.deleted == 1;
    }

    /**
     * 标记删除
     * 
     * 将deleted字段设置为1，表示逻辑删除。
     * 注意：这只是设置标记，实际删除需要调用相应的删除方法。
     */
    public void markDeleted() {
        this.deleted = 1;
    }

    /**
     * 标记未删除
     * 
     * 将deleted字段设置为0，表示恢复记录。
     */
    public void markNotDeleted() {
        this.deleted = 0;
    }

    @Override
    public String toString() {
        return "BaseEntity{" +
                "tenantId='" + tenantId + '\'' +
                ", createBy=" + createBy +
                ", createTime=" + createTime +
                ", updateBy=" + updateBy +
                ", updateTime=" + updateTime +
                ", deleted=" + deleted +
                ", remark='" + remark + '\'' +
                '}';
    }
}
